home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 23 code / Multipane Dialogs Code / MPDialogs.h < prev    next >
Encoding:
Text File  |  1995-04-18  |  16.5 KB  |  498 lines  |  [TEXT/MMCC]

  1. /* Multi-Pane Dialog (MPD)
  2.  * By Norman Franke
  3.  */
  4.  
  5. // Required headers.
  6. #ifndef __DIALOGS__
  7. #include <Dialogs.h>
  8. #endif
  9.  
  10. #ifndef __LISTS__
  11. #include <Lists.h>
  12. #endif
  13.  
  14. #ifndef __FONTS__
  15. #include <Fonts.h>
  16. #endif
  17.  
  18. #ifndef __TEXTUTILS__
  19. #include <TextUtils.h>
  20. #endif
  21.  
  22.  
  23. /********************************************************************************
  24.  *
  25.  * Multi-Pane Dialog Constants
  26.  *
  27.  ********************************************************************************/
  28.  
  29. // Return codes
  30. #define kNotHandled        0
  31. #define kHandled        -1
  32. #define keNullData        1
  33. #define keBadPane        2
  34. #define keBadItem        3
  35. #define keWrongSize        4
  36.  
  37. // Standard item numbers in dialogs.
  38. #define kBOk            1
  39. #define kBCancel        2
  40. #define kBRevert        3
  41. #define kBFactory        4
  42. #define kIconBox        5
  43. #define kKeyStrings        6
  44. #define kLine            7
  45.  
  46. // Action messages for use in the various Action Procedures.
  47. #define kR2TAction        0
  48. #define kP2TAction        1
  49. #define kT2PAction        2
  50. #define kT2RAction        3
  51. #define kCalcAction        4
  52. #define kInitAction        5
  53. #define kClickAction    6
  54. #define kValidateAction    7
  55.  
  56. // Types of Action Procedures used in InstallAction and RemoveAction.
  57. #define kItemAction        1
  58. #define kEditAction        2
  59. #define kGroupAction    3
  60. #define kDefAction        4
  61.  
  62. // Arrow Keys on the keyboard.
  63. #define kLeftArrow        0x1c
  64. #define kRightArrow        0x1d
  65. #define kUpArrow        0x1e
  66. #define kDownArrow        0x1f
  67.  
  68. // Special resource types used here.
  69. #define kDTL            'DTL#'
  70. #define kGROUP            'DGRP'
  71.  
  72. // Resources for the List pseudo-CDEF.
  73. #define rIconDef        130
  74.  
  75. /********************************************************************************
  76.  *
  77.  * Multi-Pane Dialog Data Types and Universal Procedure Pointers
  78.  *
  79.  ********************************************************************************/
  80.  
  81. // Radio Group linked list.
  82. typedef struct RadioGroup {
  83.     struct RadioGroup *next;
  84.     short pane;
  85.     short num;
  86.     short items[1];
  87. } RadioGroup, *RadioGroupPtr;
  88.  
  89. #if USESROUTINEDESCRIPTORS
  90. #define kCallConvention kPascalStackBased
  91. #endif
  92.  
  93. // Types for the Action procedures.
  94. typedef short ClickActionProc(short, DialogPtr, short, short);
  95. typedef ClickActionProc *ClickActionPtr;
  96.  
  97. #if USESROUTINEDESCRIPTORS
  98. enum {
  99.     kClickProcInfo = kCallConvention |
  100.         STACK_ROUTINE_PARAMETER(1, sizeof(short)) |
  101.         STACK_ROUTINE_PARAMETER(2, sizeof(DialogPtr)) |
  102.         STACK_ROUTINE_PARAMETER(3, sizeof(short)) |
  103.         STACK_ROUTINE_PARAMETER(4, sizeof(short)) |
  104.         RESULT_SIZE(sizeof(short))
  105. };
  106.  
  107. typedef UniversalProcPtr ClickActionUPP;
  108.  
  109. #define CallClickActionProc(userRoutine, a1, a2, a3, a4)        \
  110.         CallUniversalProc((UniversalProcPtr)(userRoutine), kClickProcInfo, a1, a2, a3, a4)
  111. #define NewClickActionProc(userRoutine)        \
  112.         (ClickActionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), kClickProcInfo, GetCurrentISA())
  113. #else
  114. typedef ClickActionPtr ClickActionUPP;
  115.  
  116. #define CallClickActionProc(userRoutine, a1, a2, a3, a4) \
  117.         (*(userRoutine))(a1, a2, a3, a4)
  118. #define NewClickActionProc(userRoutine) (ClickActionUPP)(userRoutine)
  119. #endif
  120.  
  121. typedef short EditActionProc(short, Ptr, Handle, short, short);
  122. typedef EditActionProc *EditActionPtr;
  123.  
  124. #if USESROUTINEDESCRIPTORS
  125. enum {
  126.     kEditProcInfo = kCallConvention |
  127.         STACK_ROUTINE_PARAMETER(1, sizeof(short)) |
  128.         STACK_ROUTINE_PARAMETER(2, sizeof(Ptr)) |
  129.         STACK_ROUTINE_PARAMETER(3, sizeof(Handle)) |
  130.         STACK_ROUTINE_PARAMETER(4, sizeof(short)) |
  131.         STACK_ROUTINE_PARAMETER(5, sizeof(short)) |
  132.         RESULT_SIZE(sizeof(short))
  133. };
  134.  
  135. typedef UniversalProcPtr EditActionUPP;
  136.  
  137. #define CallEditActionProc(userRoutine, a1, a2, a3, a4, a5)        \
  138.         CallUniversalProc((UniversalProcPtr)(userRoutine), kEditProcInfo, a1, a2, a3, a4, a5)
  139. #define NewEditActionProc(userRoutine)        \
  140.         (EditActionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), kEditProcInfo, GetCurrentISA())
  141. #else
  142. typedef EditActionPtr EditActionUPP;
  143.  
  144. #define CallEditActionProc(userRoutine, a1, a2, a3, a4, a5) \
  145.         (*(userRoutine))(a1, a2, a3, a4, a5)
  146. #define NewEditActionProc(userRoutine) (EditActionUPP)(userRoutine)
  147. #endif
  148.  
  149. typedef short GroupActionProc(short, RadioGroupPtr, Handle, DialogPtr, Ptr, short, short);
  150. typedef GroupActionProc *GroupActionPtr;
  151.  
  152. #if USESROUTINEDESCRIPTORS
  153. enum {
  154.     kGroupProcInfo = kCallConvention |
  155.         STACK_ROUTINE_PARAMETER(1, sizeof(short)) |
  156.         STACK_ROUTINE_PARAMETER(2, sizeof(RadioGroupPtr)) |
  157.         STACK_ROUTINE_PARAMETER(3, sizeof(Handle)) |
  158.         STACK_ROUTINE_PARAMETER(4, sizeof(DialogPtr)) |
  159.         STACK_ROUTINE_PARAMETER(5, sizeof(Ptr)) |
  160.         STACK_ROUTINE_PARAMETER(6, sizeof(short)) |
  161.         STACK_ROUTINE_PARAMETER(7, sizeof(short)) |
  162.         RESULT_SIZE(sizeof(short))
  163. };
  164.  
  165. typedef UniversalProcPtr GroupActionUPP;
  166.  
  167. #define CallGroupActionProc(userRoutine, a1, a2, a3, a4, a5, a6, a7)        \
  168.         CallUniversalProc((UniversalProcPtr)(userRoutine), kGroupProcInfo, a1, a2, a3, a4, a5, a6, a7)
  169. #define NewGroupActionProc(userRoutine)        \
  170.         (GroupActionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), kGroupProcInfo, GetCurrentISA())
  171. #else
  172. typedef GroupActionPtr GroupActionUPP;
  173.  
  174. #define CallGroupActionProc(userRoutine, a1, a2, a3, a4, a5, a6, a7) \
  175.         (*(userRoutine))(a1, a2, a3, a4, a5, a6, a7)
  176. #define NewGroupActionProc(userRoutine) (GroupActionUPP)(userRoutine)
  177. #endif
  178.  
  179. typedef void DefActionProc(Ptr, short, short, short, short);
  180. typedef DefActionProc *DefActionPtr;
  181.  
  182. #if USESROUTINEDESCRIPTORS
  183. enum {
  184.     kDefProcInfo = kCallConvention |
  185.         STACK_ROUTINE_PARAMETER(1, sizeof(Ptr)) |
  186.         STACK_ROUTINE_PARAMETER(2, sizeof(short)) |
  187.         STACK_ROUTINE_PARAMETER(3, sizeof(short)) |
  188.         STACK_ROUTINE_PARAMETER(4, sizeof(short)) |
  189.         STACK_ROUTINE_PARAMETER(5, sizeof(short))
  190. };
  191.  
  192. typedef UniversalProcPtr DefActionUPP;
  193.  
  194. #define CallDefActionProc(userRoutine, a1, a2, a3, a4, a5)        \
  195.         CallUniversalProc((UniversalProcPtr)(userRoutine), kDefProcInfo, a1, a2, a3, a4, a5)
  196. #define NewDefActionProc(userRoutine)        \
  197.         (DefActionUPP) NewRoutineDescriptor((ProcPtr)(userRoutine), kDefProcInfo, GetCurrentISA())
  198. #else
  199. typedef DefActionPtr DefActionUPP;
  200.  
  201. #define CallDefActionProc(userRoutine, a1, a2, a3, a4, a5) (*(userRoutine))(a1, a2, a3, a4, a5)
  202. #define NewDefActionProc(userRoutine) (DefActionUPP)(userRoutine)
  203. #endif
  204.  
  205. // All the state used by the multi-pane dialog code.
  206. typedef struct MPDRec {
  207.     // Number of panes in the dialog
  208.     short            numPanes;
  209.     // Current pane being displayed
  210.     short            currentPane;
  211.     // Item number of first item in the panes
  212.     short            baseItems;
  213.     // List of IDs for the pane's DITLs
  214.     short            *paneIDs;
  215.     // Whether the Revert button should be enabled
  216.     short            paneDirty;
  217.     // Linked list of Radio Groups
  218.     RadioGroupPtr    radio;
  219.     // Actual and temporary storage for dialog values
  220.     Handle            theData, tmpData;
  221.     // List of icon suites
  222.     Handle            *IconHandles;
  223.     // List Manager list for the icon list
  224.     ListHandle        theList;
  225.     // Action Procedures
  226.     ClickActionUPP    ClickAction;
  227.     EditActionUPP    EditAction;
  228.     GroupActionUPP    GroupAction;
  229.     DefActionUPP    DefAction;
  230. } MPDRec, *MPDPtr, **MPDHdl;
  231.  
  232. /********************************************************************************
  233.  *
  234.  * Main Multi-Pane Dialog Routines
  235.  *
  236.  ********************************************************************************/
  237.  
  238. /* Open a new MPD.
  239.  *
  240.  * First parameter is the resource ID of the DLOG and DTL# for the dialog.
  241.  *   DTL#'s list the name and ID for each pane.
  242.  *   The ID is also for the icon group and optional DGRP resource.
  243.  * Second through fifth parameters allow custom procedure for handling:
  244.  *   - Code to set factory defaults,
  245.  *   - Actions when items are clicked on,
  246.  *   - How TextEdit fields are treated, and
  247.  *   - How Radio Groups are handled.
  248.  * Last parameter is the storage for the MPD data.
  249.  *   Passing a pointer to NULL will create a new one based on the DITLs.
  250.  */
  251. DialogPtr OpenMPDialog(short resID, DefActionUPP defAction, ClickActionUPP clickProc,
  252.     EditActionUPP editAction, GroupActionUPP groupAction, Handle *theData);
  253.  
  254. /* Remove a MPD,
  255. *    and deallocates all storage, exept the data handle.
  256.  */
  257. void CloseMPDialog(DialogPtr *dlog);
  258.  
  259. /* Handle an event in the MPD.
  260.  *
  261.  * Returns kNotHandled if the event is not for the MPD.
  262.  * The DialogPtr is set to NULL if the event caused the MPD to close.
  263.  *   (CloseMPDialog is called in this case.)
  264.  */
  265. short DoMPDialogEvent(DialogPtr *dlog, EventRecord *theEvent);
  266.  
  267. /* Determine if the current pane has more than a single edit field.
  268.  * Returns true if so.
  269.  */
  270. Boolean MultipleEditFields(DialogPtr dlog);
  271.  
  272. /* Installs an Action Procedure.
  273.  *
  274.  * First parameter is the type, second is the DialogPtr of the MPD,
  275.  *   third is the ProcPtr to the Action procedure.
  276.  * If NULL is passed for the ProcPtr, the Action procedure is reset to
  277.  *   the default action.
  278.  */
  279. short InstallAction(short aType, DialogPtr dlog, UniversalProcPtr actionProc);
  280.  
  281. /* Remove an Action Procedure.
  282.  *
  283.  * Calls InstallAction with a NULL actionProc.
  284.  */
  285. short RemoveAction(short aType, DialogPtr dlog);
  286.  
  287. /********************************************************************************
  288.  *
  289.  * Multi-Pane Dialog Data Access Routines
  290.  *
  291.  ********************************************************************************/
  292.  
  293. /* Retrieve a MPD item value.
  294.  *
  295.  * Given a MPD data handle, pane ID and item it will retrieve the
  296.  *   data into the passed pointer.
  297.  * It verifies that the length is correct, and a valid pane and item were passed.
  298.  */
  299. short GetMPDItem(Handle theData, short pane, short item, Ptr ptr, short len);
  300.  
  301. /* Store a MPD item value.
  302.  *
  303.  * Given a MPD data handle, pane ID and item it will store the
  304.  *   data from the passed pointer into the MPD data handle.
  305.  * It verifies that the length is correct, and a valid pane and item were passed.
  306.  */
  307. short SetMPDItem(Handle theData, short pane, short item, Ptr ptr, short len);
  308.  
  309. /********************************************************************************
  310.  *
  311.  * Internal Multi-Pane Dialog Routines
  312.  *
  313.  ********************************************************************************/
  314.  
  315. /* Display a pane.
  316.  *
  317.  * Removes the old pane and installes the new in the dialog.
  318.  */
  319. void InstallDITL(DialogPtr dlog, short pane);
  320.  
  321. /* Create a new empty MPD data handle.
  322.  *
  323.  * The first part of the handle is a series of long offsets into
  324.  *   the handle where the individual pane values are stored, zero terminated.
  325.  * Controls, Check boxes and non-groups Radio Buttons are stored as shorts.
  326.  * Default action is to store TextEdit fields as Str255's.
  327.  * A single short is allocated for a Radio Group.
  328.  * The end of the item list per pane is zero terminated.
  329.  */
  330. Handle MPDTemplateFromDITL(MPDHdl dataH);
  331.  
  332. /* Create a Radio Group.
  333.  *
  334.  * First parameter is the MPD, second is the pane ID,
  335.  *  third is a list of item numbers for the group (numbering local to the DITL),
  336.  *  last is the number of items in the array/group.
  337.  */
  338. short CreateMPDRadioGroup(DialogPtr dlog, short pane, short *itemList, short itemNum);
  339.  
  340. /* Create Radio Groups for a pane.
  341.  *
  342.  * First parameter is the MPD, second is the pane ID.
  343.  * This reads a DGRP resource to get the Radio Groups for a pane.
  344.  * Most of the work is done in CreateMPDRadioGroup.
  345.  */
  346. void CreateRadioGroups(DialogPtr dlog, short pane);
  347.  
  348. /* Sets MPD controls on the display to their factory settings.
  349.  *
  350.  * Given the MPD and the pane, it sets the default values for the controls on that pane.
  351.  */
  352. void SetFactoryDefault(DialogPtr dlog, short pane);
  353.  
  354. /* Toggle items in a Radio Group.
  355.  *
  356.  * Given the MPD, the specific Radio and a DITL-local number,
  357.  *   make sure it's the only Radio Button set in the group.
  358.  */
  359. void ToggleGroup(DialogPtr dlog, RadioGroupPtr group, short item);
  360.  
  361. /* Calculates the size the Radio Button needs in the MPD data handle.
  362.  *
  363.  * If the radio button is a member of a Radio Group it returns zero,
  364.  *   since radio groups are stored separately.
  365.  * Otherwise it returns sizeof(short).
  366.  * It is passed the first Radio Group and the pane and item of the control.
  367.  */
  368. short GetRadioMPDSize(RadioGroupPtr radio, short pane, short item);
  369.  
  370. /********************************************************************************
  371.  *
  372.  * Internal Multi-Pane Dialog Action Procedures
  373.  *
  374.  ********************************************************************************/
  375.  
  376. /* MPD Action Procedure.
  377.  *
  378.  * Given the MPD and pane, and
  379.  * depending on the value of the second argument it will:
  380.  *   - Create a working copy of the MPD data handle for use,
  381.  *   - Call P2TMPDAction to save the controls,
  382.  *   - Call T2PMPDAction to set the controls,
  383.  *   - Save the temporary results of the MPD into the MPD data handle,
  384.  *   - Call P2TMPDAction or T2PMPDAction.
  385.  */
  386. short HandleMPDAction(DialogPtr dlog, short message, short pane);
  387.  
  388. /* Transfer the MPD controls as displayed into the temporary MPD data handle.
  389.  *
  390.  * When the user switches panes, the values need to be saved.
  391.  * It calls the Action Procedure for Radio Button and TextEdit fields.
  392.  * If a radio button is not in a group, it is treated like a check box.
  393.  */
  394. short P2TMPDAction(DialogPtr dlog, short pane);
  395.  
  396. /* Transfer the values from the temporary MPD data handle to the display.
  397.  *
  398.  * When the user switches panes, the values need to be restored.
  399.  * It calls the Action Procedure for Radio Button and TextEdit fields.
  400.  * If a radio button is not in a group, it is treated like a check box.
  401.  */
  402. short T2PMPDAction(DialogPtr dlog, short pane);
  403.  
  404. /* Handler for when a user clicks on a Radio Button.
  405.  *
  406.  * Returns kNotHandled if the radio button is not in a Radio Group.
  407.  * It gets passed the MPD and the DITL local item number hit.
  408.  */
  409. short HandleRadioGroup(DialogPtr dlog, short item);
  410.  
  411. /* Do Radio Group Action Procedure.
  412.  *
  413.  * Calls the Group Action Procedure for each Radio Group.
  414.  * For kP2TAction and kT2PAction dlog is the MPD,
  415.  *   for kCalcAction and kInitAction it is the MPDHdl.
  416.  */
  417. short DoGroupAction(short mType, DialogPtr dlog, Ptr hPtr, short pane, short *item);
  418.  
  419. /********************************************************************************
  420.  *
  421.  * Default Action Procedures
  422.  *
  423.  ********************************************************************************/
  424.  
  425. /* Set default values for a pane.
  426.  *
  427.  * Given the data pointer, length of item's storage, type, pane and DITL local item,
  428.  *   set the defaults for all the items on that pane.
  429.  * Default action sets everything to zero.
  430.  */
  431. void DefaultAction(Ptr theData, short len, short iType, short pane, short item);
  432.  
  433. /* TextEdit Action Procedure.
  434.  *
  435.  * Depending on the value of the first argument it will:
  436.  *   - Save the value of a TextEdit field, which is the actual text as a pascal string.
  437.  *   - Set the value of a TextEdit field.
  438.  *   - Return the amount of item storage needed for a TextEdit (256).
  439.  *   - Initialize the TextEdit record.
  440.  * Second parameter is the ControlHandle for the control being processed,
  441.  *   followed by the pane and item number of the control.
  442.  */
  443. short DefaultEditAction(short mType, Ptr hPtr, Handle iHandle, short pane, short item);
  444.  
  445. /* Action Procedure when something is clicked or validated.
  446.  *
  447.  * The first parameter specifies the message type:
  448.  *   kInitAction, kValidateAction or kClickAction
  449.  * For clicking and initialization:
  450.  *   Nothing happens for buttons and controls,
  451.  *   Radio groups are handled in HandleRadioGroup or are toggled if it can't, and
  452.  *   Check boxes are simply toggled.
  453.  * Validation always succeeds.
  454.  */
  455. short DefaultClickAction(short mType, DialogPtr dlog, short pane, short item);
  456.  
  457. /* Radio Group Action Procedure.
  458.  *
  459.  * Depending on the value of the first argument it will:
  460.  *   - Save the value of a Radio Group, which is the index of the control in the group.
  461.  *   - Set the value of a Radio Group.
  462.  *   - Return the amount of item storage needed for a Radio Group.
  463.  *   - Initialize the value of the Radio Group to 1.
  464.  * The second argument is the Radio Group being processed, third is the MPDHdl,
  465.  *   fourth the DialogPtr, fifth a pointer to the storage pointer (which is updated
  466.  *   here), lastly the pane and item number of the control in the group.
  467.  */
  468. short DefaultGroupAction(short mType, RadioGroupPtr group, Handle H, DialogPtr dlog,
  469.     Ptr hPtr, short pane, short item);
  470.  
  471.  
  472. /* Useful routines I use a lot.
  473.  * By Norman Franke
  474.  */
  475.  
  476. // ******************** Gray Line
  477. pascal void DrawGray (DialogPtr theDialog, short theItem);
  478. void SetItemToGray(DialogPtr dlog, short item);
  479.  
  480. // ******************** Command Key Equivalents
  481. pascal Boolean keyAltFilter(DialogPtr dlg, short theItem, short offset, EventRecord *event, short *item);
  482.  
  483. // ******************** Menu
  484. void AbleDisItem(short menu, short item, short flag);
  485.  
  486. // ******************** Grow Icon
  487. void MyDrawGrow(WindowPtr win);
  488.  
  489. // ******************** Dialog & Window
  490. void HiliteItem(DialogPtr dlgPtr, short itemNo, short state);
  491. ControlHandle GetItemHandle(DialogPtr theDialog, short item);
  492. short GetDItemValue(DialogPtr dlgPtr, short itemNo);
  493. void AbleDItem(DialogPtr dlog, short item, short state);
  494. DialogPtr MyGetCenteredDialog(short id, DialogPtr storage, WindowPtr relatedWindow, WindowPtr behind);
  495.  
  496. // ******************** Miscelaneous
  497. void Pstrcpy(Str255, ConstStr255Param);
  498.